package lastRites.game.networking;

import java.io.IOException;
import java.util.Vector;

import lastRites.entities.Player;
import lastRites.enums.BlockType;
import lastRites.enums.CreatureType;
import lastRites.enums.GameStatus;
import lastRites.enums.TileSetName;
import lastRites.game.LastRites;
import lastRites.game.networking.NetworkPackets.GameStartPacket;
import lastRites.game.networking.NetworkPackets.MapBlockPacket;
import lastRites.game.terrain.TerrainBlock;
import lastRites.ui.Inventory;
import lastRites.ui.Item;
import lastRites.ui.ItemStack;

import org.newdawn.slick.Image;
import org.newdawn.slick.geom.Rectangle;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryonet.Client;
import com.esotericsoftware.kryonet.EndPoint;
import com.esotericsoftware.kryonet.Server;
import com.esotericsoftware.minlog.Log;

public class Network {
	public static final int	port	= 6112;

	// private Logger logger = Logger.getLogger("DungeonDigger.Network");

	/** @return A Client, started and ready to connect with all classes defined in {@link Network}'s register method.
	 * @throws IOException */
	public static Client setupClient() {
		Client c = new Client( 128000, 2048 );
		Network.register( c );
		c.start();
		c.addListener( new ClientListener() );
		return c;
	}

	/** @return A Server, started and listening on the port set on the {@link Network} class.
	 * @throws IOException */
	public static Server setupServer() throws IOException {
		Server s = new Server( 128000, 2048 );
		Network.register( s );
		s.start();
		s.bind( Network.port );
		s.addListener( new ServerListener() );
		return s;
	}

	/** @return A Server, started and listening on the port set on the {@link Network} class. Will simply affirm anything the player requests.
	 * @throws IOException */
	public static Server setupSinglePlayerServer() throws IOException {
		Server s = new Server( 128000, 2048 );
		Network.register( s );
		s.start();
		s.bind( Network.port );
		s.addListener( new SinglePlayerServerListener() );
		return s;
	}

	/** This registers objects that are going to be sent over the network.
	 * @param endPoint */
	public static void register(EndPoint endPoint) {
		Kryo kryo = endPoint.getKryo();
		// TODO: LOGGER SETTINGS
		Log.set( Log.LEVEL_DEBUG );
		kryo.register( TileSetName.class );
		kryo.register( Player.class );
		kryo.register( Rectangle.class );
		kryo.register( Inventory.class );
		kryo.register( CreatureType.class );
		kryo.register( BlockType.class );
		kryo.register( Image.class );
		kryo.register( ItemStack.class );
		kryo.register( Item.class );
		kryo.register( float[].class );
		kryo.register( NetworkPackets.MapBlockPacket.class );
		kryo.register( NetworkPackets.TextDisplayPacket.class );
		kryo.register( NetworkPackets.ChatPacket.class );
		kryo.register( NetworkPackets.LoginRequest.class );
		kryo.register( NetworkPackets.LoginResponse.class );
		kryo.register( NetworkPackets.SignOff.class );
		kryo.register( NetworkPackets.GameStartPacket.class );
		kryo.register( NetworkPackets.GameJoinPacket.class );
		kryo.register( NetworkPackets.PlayerInfoPacket.class );
		kryo.register( NetworkPackets.PlayerListPacket.class );
		kryo.register( NetworkPackets.TilesResponse.class );
		kryo.register( NetworkPackets.TilesRequest.class );
		kryo.register( NetworkPackets.TileResponse.class );
		kryo.register( TerrainBlock.class );
		kryo.register( TerrainBlock[].class );
		kryo.register( TerrainBlock[][].class );
		kryo.register( NetworkPackets.WholeMapPacket.class );
		kryo.register( Vector.class );
		kryo.register( NetworkPackets.PlayerMovementUpdate.class );
		kryo.register( NetworkPackets.PlayerMovementRequest.class );
		kryo.register( NetworkPackets.PlayerMovementResponse.class );
	}

	public static void sendMap() {
		int count = 0;
		for( int row = 0; row < LastRites.CURRENT_WORLD.getBlocks().length; row++ ) {
			for( int col = 0; col < LastRites.CURRENT_WORLD.getBlocks()[0].length; col++ ) {
				LastRites.SERVER.sendToAllTCP( new MapBlockPacket( LastRites.CURRENT_WORLD.getBlocks()[row][col] ) );
				count++;
				System.out.println( "sent " + count );
			}
		}
		LastRites.SERVER.sendToAllTCP( new GameStartPacket( 50, 50 ) );
		LastRites.GAME_STATUS = GameStatus.HOSTINGGAME;
	}
}
